#
# Demo chemistry atom types.
#
# This file is quite complex. It has six major sections:
# -- Setup CMake to find everything it needs.
# -- Generate the c++, scheme and python wrappers from the
#    master type defintion file.
# -- Build the C++ library holding the needed machinery.
# -- Build a guile scheme module.
# -- Build a python module.
# -- Install all of the above into the root filesystem.
#
# --------------------------------------------------------------
# Part Zero: Set up CMake
# You might also want to make a copy of the CMakefile at the
# root of this project, and edit it down to suit your needs.

# This is commented out, because it's not directly needed for this demo.
# IF (NOT DEFINED ATOMSPACE_DATA_DIR)
# 	SET (ATOMSPACE_DATA_DIR "${COGUTIL_DATA_DIR}")
# ENDIF (NOT DEFINED ATOMSPACE_DATA_DIR)
#
# INCLUDE("${ATOMSPACE_DATA_DIR}/cmake/OpenCogMacros.cmake")
# INCLUDE("${ATOMSPACE_DATA_DIR}/cmake/OpenCogGuile.cmake")
# INCLUDE("${ATOMSPACE_DATA_DIR}/cmake/OpenCogCython.cmake")

# --------------------------------------------------------------
# Part One: Build the various language wrappers.
#
# The `chem_types.script` file defines the types; the other three
# file are c++ files that are autogenerated in the build directory.
OPENCOG_GEN_CXX_ATOMTYPES(chem_types.script
	chem_types.h
	chem_types.definitions
	chem_types.inheritance)

# As above, but the guile scheme bindings are generated.
OPENCOG_GEN_SCM_ATOMTYPES(chem_types.script chem_types.scm)

IF (HAVE_PYTHON)
	# Same, for Python.
	OPENCOG_GEN_PYTHON_ATOMTYPES(chem_types.script chem_types.pyx)
ENDIF ()

# A "phony" target, which can be used in other places to guarantee
# that the bindings are built before any code that uses the bindings.
# For example, this is used in the `apps` CMakefile, to make sure that
# the types are built before the apps.
IF (HAVE_PYTHON)
	SET(CHEM_TYPES_PYX chem_types.pyx)
ENDIF (HAVE_PYTHON)

ADD_CUSTOM_TARGET(chem_demo_atom_types
	DEPENDS chem_types.h chem_types.scm ${CHEM_TYPES_PYX}
)

# For OCaml, see the `ocaml` subdirectory in the main project.
# Building the OCaml bindings is more complex. Note that, in
# general, OCaml and AtomSpace clash in the notion of a type:
# OCaml wants all types to be compile-time types, whereas the
# the AtomSapce defines them at runtime (and does a lot of
# run-time type-casting). This is at odds to OCaml, and an
# elegant solution to allowing these two systems to co-exist
# has not yet been invented.

# --------------------------------------------------------------
# Part Two: Build the C++ library
#
# The chem_types.h file is written to the build directory
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR})

# This will build the `libchem-demo-types.so` shared library
# containing all the needed machinery to make things work.
# The `Carbon14Node.cc` file is optional and can be omitted;
# it demos an "active" AtomSpace atom.
ADD_LIBRARY (chem-demo-types SHARED
	chem_types.h
	ChemTypes.cc
	Carbon14Node.cc
)

# Without this, parallel make will race and attempt to build the
# shared library before the needed generated files are created!
ADD_DEPENDENCIES(chem-demo-types chem_demo_atom_types)

# Add linking targets for the library.
# Generally, you should use ${ATOMSPACE_atomtypes_LIBRARY} but
# this definition is not available in this repo.
TARGET_LINK_LIBRARIES(chem-demo-types
	atom_types
	atombase
	atomspace
	# ${ATOMSPACE_atomtypes_LIBRARY}
)

# --------------------------------------------------------------
# Part Three: Build the scheme module
#
# The AtomSpace unit-test infrastructure allows the unit tests
# to be run *before* installing files into the filesystem. The
# price for this is the need for the "config" directives, which
# tell scheme were to find modules in the build directory. This
# mostly just clutters up the text below.

DECLARE_GUILE_CONFIG_TARGET(CHEMODEMO_CONFIG
	"opencog chemodemo-config" "FOO_TEST")

ADD_GUILE_EXTENSION(CHEMODEMO_CONFIG
	chem-demo-types "opencog-ext-path-chemodemo")

WRITE_GUILE_CONFIG(
	${GUILE_BIN_DIR}/opencog/chemodemo-config.scm
	CHEMODEMO_CONFIG TRUE
)

WRITE_GUILE_CONFIG(
	${GUILE_BIN_DIR}/opencog/chemodemo-config-installable.scm
	CHEMODEMO_CONFIG FALSE
)

# Define and install the actual guile module. The name here will
# be the name of the guile module; the directory path must have the
# same name.
ADD_GUILE_MODULE (FILES
	demo-types.scm
	MODULE_DESTINATION "${GUILE_SITE_DIR}/opencog/demo-types"
)

# --------------------------------------------------------------
# Part Four: Build the Python module

if (HAVE_PYTHON)
# Specify the location of the Python.h header file
INCLUDE_DIRECTORIES(
	${PYTHON_INCLUDE_DIRS}
)

# The main python module is defined in chempydemo.pyx
# It depends on the autogenerated chem_types.pyx file.
CYTHON_ADD_MODULE_PYX(chempydemo
	chem_types.pyx
)

# The shared library will be called libchempydemo.so
# The cpp file is generated by the CYTHON_ADD_MODULE_PYX above.
ADD_LIBRARY(chempydemo SHARED
	chempydemo.cpp
)

TARGET_LINK_LIBRARIES(chempydemo
	chem-demo-types
	${ATOMSPACE_LIBRARIES}
	${PYTHON_LIBRARIES}
)

# ... except python doesn't like modules called `libfoo.so` It wants
# to find it's modules in `foo.so` instead.  So this causes CMake to
# rename the shared object to a name that python likes.
SET_TARGET_PROPERTIES(chempydemo PROPERTIES
	PREFIX ""
	OUTPUT_NAME chempydemo)

ENDIF (HAVE_PYTHON)
# --------------------------------------------------------------
# Part Five: Install the demo system into the root file system.
#
# Install the C++ shared library.
INSTALL (TARGETS
	chem-demo-types
	LIBRARY DESTINATION "lib${LIB_DIR_SUFFIX}/opencog"
)

INSTALL (FILES
	${CMAKE_CURRENT_BINARY_DIR}/chem_types.h
	DESTINATION "include/opencog/demo-types"
)

INSTALL (FILES
	${CMAKE_CURRENT_BINARY_DIR}/atom_names.h
	DESTINATION "include/opencog/demo-types"
)

INSTALL (FILES
	${CMAKE_CURRENT_BINARY_DIR}/chem_types.scm
	DESTINATION "${GUILE_SITE_DIR}/opencog/demo-types/"
)

INSTALL(
	FILES ${GUILE_BIN_DIR}/opencog/chemodemo-config-installable.scm
	DESTINATION ${GUILE_SITE_DIR}/opencog
	RENAME chemodemo-config.scm
)

IF (HAVE_PYTHON)
INSTALL(TARGETS
	chempydemo
	DESTINATION "${PYTHON_DEST}"
)
ENDIF (HAVE_PYTHON)

# The below allows you to install the above by saying
# `sudo make install-demotypes`
ADD_CUSTOM_TARGET (install-demotypes
	DEPENDS examples
	WORKING_DIRECTORY .
	COMMAND $(MAKE) install
	COMMENT "Installing examples ..."
)

# --------------------------------------------------------------
